
/*
Copyright 2009 David Revell

This file is part of SwiFTP.

SwiFTP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SwiFTP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SwiFTP.  If not, see <http://www.gnu.org/licenses/>.
*/

package lfr.ustc.ftp;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.wifi.WifiManager;
import android.os.IBinder;

public class FtpServer extends Service implements Runnable {
	protected static Thread serverThread = null;
	protected ServerSocket listenSocket;
	protected static int port;
	boolean listenSocketIsStart = false;
	private List<SocketManager> sessionThreads = new ArrayList<SocketManager>();
	private static SharedPreferences settings = null;

	public IBinder onBind(Intent intent) {
		return null;
	}

	public void onCreate() {
		Context myContext = CommonSettings.getContext();
		if (myContext == null) {
			myContext = getApplicationContext();
			if (myContext != null) {
				CommonSettings.setContext(myContext);
			}
		}
		init();
	}

	private void init() {
		settings = CommonSettings.getSettings();
		port = 8899;

	}

	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		while (serverThread != null) {
			serverThread.stop();
			serverThread = null;
		}
		serverThread = new Thread(this);
		serverThread.start();
	}

	public static boolean isRunning() {
		if (serverThread == null) {
			return false;
		}
		return true;
	}

	public void onDestroy() {
		StopSessions();
		serverThread = null;

		if (listenSocket != null) {
			try {
				listenSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	public void run() {

		try {
			listenSocket = new ServerSocket();
			listenSocket.setReuseAddress(true);
			listenSocket.bind(new InetSocketAddress(port));
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		while (true) {
			if (!listenSocketIsStart) {
				new Thread() {
					public void run() {
						listenSocketIsStart = true;
						try {
							while (true) {
								Socket clientSocket = listenSocket.accept();
								SocketManager newSession = new SocketManager(
										clientSocket,
										new DataSocket());
								newSession.start();
								registerSessionThread(newSession);
							}
						} catch (Exception e) {
						}
					}
				}.start();
			}
		}
	}

	private void StopSessions() {
		synchronized (this) {
			for (SocketManager sessionThread : sessionThreads) {
				if (sessionThread != null) {
					sessionThread.closeDataSocket();
					sessionThread.closeSocket();
				}
			}
		}
	}

	public static String getWifiIp() {
		Context myContext = CommonSettings.getContext();
		if (myContext == null) {
			throw new NullPointerException("Global context is null");
		}
		WifiManager wifiMgr = (WifiManager) myContext
				.getSystemService(Context.WIFI_SERVICE);
		if (isWifiEnabled()) {
			int ipAsInt = wifiMgr.getConnectionInfo().getIpAddress();

			return IntToIp(ipAsInt);
		} else {
			return "192.168.1.1";
		}
	}
	private static String IntToIp(int i) {
		return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)
				+ "." + ((i >> 24) & 0xFF);
	}

	public static boolean isWifiEnabled() {
		Context myContext = CommonSettings.getContext();
		if (myContext == null) {
			throw new NullPointerException("Global context is null");
		}
		WifiManager wifiMgr = (WifiManager) myContext
				.getSystemService(Context.WIFI_SERVICE);
		if (wifiMgr.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
			return true;
		} else {
			return false;
		}
	}

	public void registerSessionThread(SocketManager newSession) {
		synchronized (this) {
			List<SocketManager> toBeRemoved = new ArrayList<SocketManager>();
			for (SocketManager sessionThread : sessionThreads) {
				if (!sessionThread.isAlive()) {
					try {
						sessionThread.join();
						toBeRemoved.add(sessionThread);
						sessionThread.closeSocket();
					} catch (InterruptedException e) {
					}
				}
			}
			for (SocketManager removeThread : toBeRemoved) {
				sessionThreads.remove(removeThread);
			}
			sessionThreads.add(newSession);
		}
	}
}
